#include "tcp_socket.hpp"
#include<pthread.h>

//服务端
//多线程实现

void* thread_entry(void* arg)
{
  //线程入口函数
  TcpSocket new_sock;
  //当前系统是 64 位，指针大小为 8 字节，若使用 int 会发生阶段，因此采用 long
  new_sock.set((long)arg);  //因为创建线程，我们只需要获取的是套接字描述符的值
  //完成数据收发
  while(1){
    //5、收发数据
    std::string buf;
    bool ret = new_sock.Recv(&buf);
    if(ret==false){
      //接受失败
      new_sock.Close();   //说明连接不成立----关闭套接字
      //continue;
      break;
    }
    std::cout<<"client say : "<<buf<<std::endl;

    buf.clear();
    std::cout<<"server say : ";
    fflush(stdout);
    std::cin>>buf;                                                              
    ret = new_sock.Send(buf);
    if(ret==false){
      new_sock.Close();
      //continue;  //发送数据失败，关闭套接字
      break;
    }
  }


  return NULL;
}
void creat_worker(TcpSocket new_sock)
{
  pthread_t tid;
  //因为 new_sock 是一个局部变量，因此不能传址
  int ret=pthread_create(&tid,NULL,thread_entry,(void*)new_sock.fd());  //传递 void* 参数时，我们只需要获取 TcpSocket结构体内部的描述符的值信息，因此给县城入口函数传递值即可
  if(ret!=0){
    perror("pthread_create error!\n");
    new_sock.Close();
    return ;
  }

  //成功创建线程则会自动调用县城入口函数
  //线程分离----不关心退出返回值也不需要等待
  pthread_detach(tid);
    
}


int main(int argc,char* argv[])
{
  if(argc!=3){
    std::cout<<"nUsage:./tcp_ser 192.168.75.128 9000"<<std::endl;
    return -1;
  }
  std::string ip=argv[1];
  uint16_t  port=atoi(argv[2]);

  TcpSocket lsn_sock;  //实例化一个套接字结构对象
  //服务端
  //1、创建套接字
  assert(lsn_sock.Socket()!=false);

  //2、绑定地址
  assert(lsn_sock.Bind(ip,port));
  //3、开始监听
  assert(lsn_sock.Listen());

  while(1){
    //4、建立新连接
    TcpSocket new_sock;  //新建套接字，因为客户端连接可能不止一个，因此需要循环进行建立连接
    std::string cli_ip;
    uint16_t cli_port;
    bool ret=lsn_sock.Accept(&new_sock,&cli_ip,&cli_port);
    if(ret==false){
      //一次客户端的新建连接失败，则继续处理下一个客户端请求
      continue;
    }
    std::cout<<"new client: "<<cli_ip<<" : "<<cli_port<<std::endl;

    //创建多线程实现多执行流
    creat_worker(new_sock);
/*
    while(1){
      //5、收发数据
      std::string buf;
      ret = new_sock.Recv(&buf);
      if(ret==false){
        //接受失败
        new_sock.Close();   //说明连接不成立----关闭套接字
        //continue;
        break;
      }
      std::cout<<cli_ip<<" : "<<cli_port<<"say : "<<buf<<std::endl;

      buf.clear();
      std::cout<<"server say : ";
      fflush(stdout);
      std::cin>>buf;
      ret = new_sock.Send(buf);
      if(ret==false){
        new_sock.Close();
        //continue;  //发送数据失败，关闭套接字
        break;
      }
    }*/
  }
  //6、关闭套接字
  lsn_sock.Close();  

  return 0;
}
